This comes about in the context of IaC refactoring. A moved block denotes that a previous resource has been renamed/refactored into a different naming resource. Without a moved block, Terraform will destroy the first resource and re-create the second resource, which is undesirable for stateful infrastructure.

Example

moved {
  from = aws_instance.a
  to = aws_instance.b
}

This tells Terraform that what was originally aws_instance.a is now aws_instance.b. No destroy and re-creation required!

Use Cases

  • Renaming a resource
  • Enabling count or for_each for a resource
  • Renaming a module call
  • Enabling count or for_each for a module call
  • Splitting one module into multiple1

Removing moved blocks

moved blocks serve as migration history. It can accumulate over time. Keep in mind that while it is tempting to remove moved blocks

Warning

Removing moved blocks is a breaking change

If a resource has been renamed twice, keep two moved blocks:

moved {
  from = aws_instance.a
  to   = aws_instance.b
}
 
moved {
  from = aws_instance.b
  to   = aws_instance.c
}

This allows users who are on aws_instance.a and aws_instance.b to simultaneously upgrade to aws_instance.c.

Footnotes

  1. The moved blocks stay in the old module and refactored parts are re-imported. Essentially the old module becomes a shim that exists for backward compatibility. Users should directly use the new modules instead.